using System;
using System.Text;
using System.Collections.Generic;

namespace AntiXssExperimental {
public class Utf8Encoder
{
static int Bits(int m, int n, int c){return ((c >> n) & ~(-2 << (m - n)));}

public static string Apply(string input){
var output = new StringBuilder(input.Length >= 16384 ? input.Length : (int)(Math.Min(16384, (long)input.Length * 3)));
int r0 = 0;int state = 0;
for (int i = 0; i < input.Length; i++){
int c = (int)input[i];
switch (state){
case (0): {
  if ((Bits(15,7,c)==0)) {
    output.Append((char)c);
    state = 0;
  } else {
    if ((!(Bits(15,7,c)==0)&&(Bits(15,11,c)==0))) {
      output.Append((char)(0xC0|Bits(10,6,c)));
      output.Append((char)(0x80|Bits(5,0,c)));
      state = 0;
    } else {
      if ((!(Bits(15,11,c)==0)&&((0xD800>c)||(c>0xDFFF)))) {
        output.Append((char)(0xE0|Bits(15,12,c)));
        output.Append((char)(0x80|Bits(11,6,c)));
        output.Append((char)(0x80|Bits(5,0,c)));
        state = 0;
      } else {
        if (((0xD800<=c)&&(c<=0xDBFF))) {
          output.Append((char)(0xF0|Bits(4,2,(1+Bits(9,6,c)))));
          output.Append((char)(((8|((1+Bits(7,6,c))&3))<<4)|Bits(5,2,c)));
          r0 = Bits(1,0,c);
          state = 1;
        } else {
          throw new Exception("InvalidInput");
        }
      }
    }
  }
break;}
case (1): {
  if (((0xDC00<=c)&&(c<=0xDFFF))) {
    output.Append((char)((((((Bits(11,4,r0)<<1)|1)<<3)|Bits(2,0,r0))<<4)|Bits(9,6,c)));
    output.Append((char)(0x80|Bits(5,0,c)));
    r0 = 0;
    state = 0;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
default: {
  throw new Exception("Utf8Encoder");
}
}
}
switch (state){
case (0): {
break;}
case (1): {
  throw new Exception("InvalidInput");
break;}
default: {
  throw new Exception("Utf8Encoder");
}
}
return output.ToString();
}
}
}
